package utils

import (
	list2 "container/list"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type Config struct {
	Ip   string `json:"ip"`
	Port int    `json:"port"`
}

func PrintIP() {
	addr, _ := net.InterfaceAddrs()
	for _, value := range addr {
		if ipnet, ok := value.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				fmt.Println(ipnet.IP.String())
			}
		}
	}
}

func GetIpAndPort(dir string) Config {
	path := dir + "/config/config.json"
	file, err := os.Open(path)
	CheckError(err, "文件找不到")

	b, err := ioutil.ReadAll(file)
	CheckError(err, "文件读取异常")
	jsonStr := string(b)
	print(jsonStr + "\n")
	var config Config
	err = json.Unmarshal(b, &config)
	CheckError(err, "json解析失败")
	return config
}

func CheckError(e error, s string) {
	if e != nil {
		panic(s)
	}
}

func CheckErr(e error) {
	if e != nil {
		panic(e)
	}
}

func ReturnError(e error, context *gin.Context, code int, msg string) bool {
	if e != nil {
		context.JSON(code, HttpData{
			Code: code,
			Data: msg,
		})
		return true
	}
	return false
}

func ReturnErr(e error, context *gin.Context) bool {
	if e != nil {
		context.JSON(400, HttpData{
			Code: 400,
			Data: "服务器异常",
		})
		return true
	}
	return false
}

func ReturnLogicErr(context *gin.Context, code int, msg string) {
	context.JSON(400, HttpData{
		Code: code,
		Data: msg,
	})
}

func IsValidMediaFile(info os.FileInfo) bool {
	if info.IsDir() {
		return false
	}
	name := info.Name()
	if strings.HasPrefix(name, ".") {
		return false
	}

	if strings.HasSuffix(name, ".mp4") || strings.HasSuffix(name, ".mkv") ||
		strings.HasSuffix(name, ".avi") || strings.HasSuffix(name, ".rm") ||
		strings.HasSuffix(name, ".rmvb") || strings.HasSuffix(name, ".ts") ||
		strings.HasSuffix(name, ".flv") || strings.HasSuffix(name, ".wmv") ||
		strings.HasSuffix(name, ".m4v") || strings.HasSuffix(name, ".3gp") {
		return true
	}
	return false
}

func FindNumberFromFileName(info os.FileInfo) (int, error) {
	name := info.Name()
	regexStr := "(\\d{1,})"
	re, _ := regexp.Compile(regexStr)
	sub := re.FindSubmatch([]byte(name))
	println(string(sub[0]))
	return strconv.Atoi(string(sub[0]))
}

type HandlerFunc func(e *list2.Element) bool

func ListOperation(list *list2.List, test HandlerFunc) {
	for e := list.Front(); e != nil; e = e.Next() {
		if test(e) {
			break
		}
	}
}

func PrintList(list *list2.List) {
	ListOperation(list, func(e *list2.Element) bool {
		fmt.Printf(e.Value.(string) + ",")
		return false
	})
	fmt.Println("")
}

func SortFile(list *list2.List) *list2.List {
	var newList = list2.New()
	var numMap = make(map[string]int)
	for e := list.Front(); e != nil; e = e.Next() {
		var file = e.Value.(os.FileInfo)
		n, _ := FindNumberFromFileName(file)
		numMap[file.Name()] = n
		if newList.Len() == 0 {
			newList.PushBack(file.Name())
			continue
		}

		var eTemp *list2.Element
		for newE := newList.Front(); newE != nil; newE = newE.Next() {
			var newName = newE.Value.(string)
			var newN = numMap[newName]
			if n < newN {
				eTemp = newE
				break
			}
		}
		if eTemp == nil {
			newList.PushBack(file.Name())
		} else {
			newList.InsertBefore(file.Name(), eTemp)
		}
	}
	return newList
}
